package com.sgcc.system.aop;

import com.sgcc.common.redis.service.RedisService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/*
计算mybatis执行sql语句时间
 */
@Aspect
@Component
public class MapperAspect {

    private static final Logger log = LoggerFactory.getLogger(MapperAspect.class);

    private static final String SQL_TIME = "SQL_TIME";

    @Autowired
    private RedisService redisService;

    @AfterReturning("execution(* com.sgcc.system.mapper..*Mapper.*(..))")
    public void logServiceAccess(JoinPoint joinPoint) {
        log.info("Completed: " + joinPoint);
    }


    /** * 监控Mapper包及其子包的所有public方法 */
    @Pointcut("execution(* com.sgcc.system.mapper..*Mapper.*(..))")
    private void pointCutMethod() {
    }

    /** * 声明环绕通知 * @param pjp * @return * @throws Throwable */
    @Around("pointCutMethod()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long begin = System.nanoTime();
        Object obj = pjp.proceed();
        long end = System.nanoTime();

        long millisecond = (end - begin) / 1000000;

        log.info("调用Mapper方法：{}，参数：{}，执行耗时：{}纳秒，耗时：{}毫秒",
                pjp.getSignature().toString(), Arrays.toString(pjp.getArgs()),
                (end - begin), millisecond);

        Map<String, Long> sqlMap = redisService.getCacheObject(SQL_TIME);
        if(sqlMap == null){
            sqlMap = new HashMap<>();
            sqlMap.put("time",millisecond);
            sqlMap.put("num",1L);
        }else {
            if(sqlMap.get("time") == null ){
                sqlMap.put("time",millisecond);
                sqlMap.put("num",1L);
            }else{
                sqlMap.put("time",sqlMap.get("time") + millisecond);
                sqlMap.put("num",sqlMap.get("num") + 1);
            }
        }
        redisService.setCacheObject(SQL_TIME, sqlMap,30L, TimeUnit.DAYS);
        return obj;
    }
}
